home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / vcpispec.zip / VCPI.DOC < prev   
Text File  |  1993-01-19  |  60KB  |  1,134 lines

  1. .MT2
  2. .MB0
  3. .PO0
  4. .PN0
  5.                       Virtual Control Program Interface
  6.          
  7.                                  Version 1.0
  8.                                 June 12, 1989
  9.          
  10.                                 VCPI SPONSORS
  11.                                 
  12.                      A.I. Architects, Inc., Peabody, MA
  13.                    Lotus Development Corp., Cambridge, MA
  14.                    Phar Lap Software, Inc., Cambridge, MA
  15.                             Quadram, Norcross, GA
  16.                         Qualitas, Inc., Bethesda, MD
  17.                 Quarterdeck Office Systems, Santa Monica, CA
  18.                      Rational Systems, Inc., Natick, MA
  19.          
  20.      VCPI Co-ordinators:               Phar Lap Software, Inc.
  21.                                        (617) 661-1510
  22.                                        Robert Moote
  23.          
  24.                                        Quarterdeck Office Systems
  25.                                        (310) 392-9851
  26.                                        Daniel Spear
  27.          
  28.                 Copyright Phar Lap Software, Inc., 1987-1989
  29.                Copyright Quarterdeck Office Systems, 1987-1989
  30.          
  31.     This specification may be duplicated provided it is reproduced in its 
  32.                entirety, including the above copyright notice.
  33.  
  34.  
  35.  
  36.  
  37.                  Version 1.0 Specification Revision History
  38.          
  39.      June 12, 1989         Final revision approved by attendees of the VCPI 
  40.                            Developer's Conference, held at the offices of Phar 
  41.                            Lap Software on April 25, 1989.  Attendees included 
  42.                            the following VCPI sponsors:  A.I. Architects, 
  43.                            Inc., Lotus Development Corporation, Phar Lap 
  44.                            Software, Inc., Qualitas, Inc., Quarterdeck Office 
  45.                            Systems, Rational Systems, Inc.; and the following 
  46.                            observers:  Compaq Computer Corporation, Intel 
  47.                            Corporation.
  48.          
  49.      May 8, 1989           Revision incorporating modifications agreed upon at 
  50.                            the VCPI Developer's Conference.  This revision was 
  51.                            distributed for approval to all conference 
  52.                            attendees.
  53.          
  54.      March 31, 1989        A more detailed and explicit revision of the 
  55.                            December 1987 specification, drafted for review at 
  56.                            the VCPI Developer's Conference.
  57.          
  58.      December 21, 1987     First revision of the specification, written by 
  59.                            Phar Lap Software, Inc., and Quarterdeck Office 
  60.                            Systems.
  61.          
  62.  
  63. 1.0  Background
  64.          
  65. The Intel 80386 microprocessor has three fundamental operating modes.  Real 
  66. mode is provided for backward compatibility with existing 8086 programs.  
  67. Protected mode allows programs written specifically for the 80386 to take 
  68. advantage of the larger address space available.  Virtual 8086 (V86) mode, 
  69. like real mode, is used to run 8086 programs.  However, V86 mode runs under 
  70. the control of a protected mode operating environment.  This provides certain 
  71. advantages, chiefly the ability to enable the paging hardware of the 80386 and 
  72. thus run multiple 8086 programs simultaneously, and also the ability to make 
  73. arbitrary physical memory available within the V86 address space of an 8086 
  74. program.  (The 80486 microprocessor provides the same architecture and 
  75. operating modes as the 80386, thus software written for the 80386 runs without 
  76. modification on an 80486).
  77.          
  78. The capabilities of the 8086 have spawned the creation of several new kinds of 
  79. control programs that can run under MS-DOS on a 386 machine.  To date, these 
  80. programs fall into three basic categories:  (1) protected mode run-time 
  81. environments, which allow an application program to execute in protected mode 
  82. under MS-DOS;  (2) EMS emulators, which use V86 mode to make all the memory on 
  83. the machine available to 8086 programs which use EMS (Lotus/Intel/Microsoft 
  84. Expanded Memory Specification) memory, and, (3) multitasking environments 
  85. which use V86 mode to multitask 8086 MS-DOS programs, while still giving each 
  86. 8086 program a full 640Kb of physical memory (or more, if they use EMS 
  87. memory).  Such multitasking environments typically run in conjunction with a 
  88. separate EMS emulator, or implement the EMS interface as part of the 
  89. multitasker.  For the remainder of this specification, the terms "DOS-
  90. Extender," "EMS emulator," and "multitasker," respectively, will be used to 
  91. refer to these program categories.
  92.          
  93. Since these control programs run under MS-DOS, it is desirable to make them 
  94. compatible with each other, so that users don't have to turn off one control 
  95. program in order to run an application under another control program.  The 
  96. purpose of this document is to specify an interface that allows these classes 
  97. of control programs to coexist successfully.  This interface is called the 
  98. Virtual Control Program Interface, or VCPI.
  99.          
  100. 2.0  Areas of Conflict
  101.          
  102. There are a variety of resource contention issues which must be solved to 
  103. allow multiple 386 control programs to coexist.  The section below summarizes 
  104. each of these issues.
  105.          
  106. 2.1  Extended Memory Allocation
  107.          
  108. Because DOS only knows about memory below one MB, there is no universally used 
  109. method in the DOS environment for allocating and freeing extended memory 
  110. (memory above one MB).  The following existing techniques are available for 
  111. allocating extended memory on both 80286 and 80386 PCs:
  112.          
  113.      1. Memory can be allocated "top down" by taking over the BIOS extended 
  114.         memory size system call (INT 15h function 88h) and reporting less 
  115.         extended memory available than is actually present on the machine. 
  116.         This method allocates a contiguous block of memory starting at the top 
  117.         of extended memory and growing downward.  See Appendix A.1 for a 
  118.         description of top down allocation.
  119.          
  120.      2. Memory can be allocated "bottom-up" by taking over the PC reboot 
  121.         interrupt (INT 19h) and installing a signature block and allocation 
  122.         size marker in the interrupt handler, and boot block with an
  123.  
  124. ______________________________________________________________________________         
  125.      VCPI Version 1.0           June 12, 1989                      Page 1
  126.  
  127.         allocation size marker at one megabyte.  This is commonly referred to 
  128.         as the VDISK technique, since it is the method employed by the 
  129.         original IBM VDISK driver.  This method allocates a contiguous block 
  130.         of memory starting at one megabyte and growing upward.  See Appendix 
  131.         A.2 for a description of bottom-up allocation.
  132.          
  133.      3. If an XMS (Microsoft Extended Memory Specification) drive is 
  134.         installed, extended memory can be allocated by making calls to the XMS 
  135.         driver.  The XMS driver reserves extended memory for an XMS memory 
  136.         pool using top-down allocation, and the allocates memory out of the 
  137.         XMS memory pool.  Copies of the XMS specification may be obtained by 
  138.         calling Microsoft at 1-800-426-9400.
  139.          
  140. A program that wishes to allocate extended memory must first determine what 
  141. extended memory is free (not in use by another program).  It does this by 
  142. calling INT 15h function 88h to obtain the top of free extended memory, and by 
  143. checking the signature of INT 19h and the boot block at one megabyte for any 
  144. bottom-up memory allocation, thus obtaining the bottom of free extended 
  145. memory.
  146.          
  147. The program can then allocate its own chunk of extended memory, either top 
  148. down by taking over INT 15h, or bottom-up by taking over INT 19h.  The top-down 
  149. allocation method is preferable because it is simpler and more robust.  The 
  150. diagram below shows an example in which three programs which use extended 
  151. memory are installed.  Program 1 (the first program installed) allocates some 
  152. extended memory bottom-up, program 2 allocates two chunks of memory, one 
  153. bottom-up and one top-down, and program 3 allocates memory top-down.
  154.          
  155. top of    _______________________________
  156. memory    |XXXXXXXXXXXXXXXXXXXXXXXXXXX|<=  allocated by program 2
  157.           |XXXXXXXXXXXXXXXXXXXXXXXXXXX|    
  158.           |---------------------------|--
  159.           |***************************|<=  allocated by program 3
  160.           |---------------------------|--
  161.           |                           |<=  free extended memory
  162.           |---------------------------|--
  163.           |XXXXXXXXXXXXXXXXXXXXXXXXXXX|<=  allocated by program 2
  164.           |XXXXXXXXXXXXXXXXXXXXXXXXXXX|
  165.           |---------------------------|--
  166.           |^^^^^^^^^^^^^^^^^^^^^^^^^^^|<=  allocated by program 1
  167. 1 MB   => |---------------------------|--
  168.           |///////////////////////////|<=  BIOS ROM, screen, etc.
  169. 640 KB => |---------------------------|--
  170.           |\\\\\\\\\\\\\\\\\\\\\\\\\\\|<=  DOS memory
  171.           |___________________________|__ 
  172.  
  173. Note that only the last installed program which allocates extended memory top-
  174. down or bottom-up (the first program in the interrupt chain for INT 15h or INT 
  175. 19h) can dynamically change its memory allocation. In the example above, only 
  176. program 2 can dynamically modify its bottom-up memory allocation, and only 
  177. program 3 can dynamically modify its top-down memory allocation.
  178.  
  179. ______________________________________________________________________________
  180.      VCPI Version 1.0           June 12, 1989                      Page 2
  181.  
  182. It is possible for VCPI memory, XMS memory and extended memory all to be 
  183. available on a single PC.  (This can occur, for example, if a VCPI driver is 
  184. installed and is given a portion of extended memory, an XMS driver is 
  185. installed and even another chunk of extended memory, and the rest of extended 
  186. memory is left free.)  Therefore, programs which can use extended memory may 
  187. wish to look for all three sources of memory.  The recommended order of use of 
  188. the different memory allocation methods is:  (1) VCPI memory, (2) XMS memory, 
  189. and, (3) extended memory.
  190.          
  191. 2.2  Mode Switching
  192.          
  193. All 386 control programs need to do some processing in protected mode, but 
  194. also need to allow standard 8086 code (such as other applications, DOS, and 
  195. the BIOS) to execute.  Therefore, they must switch between 80386 protected mode 
  196. and either real mode or V86 mode.
  197.          
  198. If two control programs both switch between protected mode and real mode, no 
  199. special problems are posed.  If, however, a control program switches between 
  200. V86 mode and protected mode, it is impossible for a second control program to 
  201. switch into protected mode.  This is because programs running in V86 mode are 
  202. executing at the least privileged level of the 80386 processor, so system-
  203. level operations will cause processor exceptions, which result in the first 
  204. control program regaining control.  Thus the first control program must 
  205. provide a method to allow subsequent control programs to switch to protected 
  206. mode and back to V86 mode again.
  207.          
  208. 2.3  8259A Interrupt Controller
  209.          
  210. The standard interrupt vectors used on the 386 PC for hardware interrupts 
  211. IRQ0 - IRQ7 are vectors 08h - 0Fh.  Unfortunately, those vectors are also used 
  212. by the 80386 processor for certain processor exceptions.  For this reason, 
  213. some 386 control programs reprogram the 8259A interrupt controller chip to 
  214. relocate IRQ0 - IRQ7 to different interrupt vectors.  Information about 
  215. reprogramming of the 8259A must be made available to all cooperating 386 
  216. control programs.
  217.          
  218. 2.4  Privileged Instructions
  219.          
  220. When the 386 processor is executing in V86 mode, it is executing at privilege 
  221. level 3 (the least privileged level), and privileged instructions cause an 
  222. exception.  These include instructions which load or store 386 system 
  223. registers, including the control registers, the debug registers, the test 
  224. registers, GDTR, LDTR, and TR.  Access to some of these registers is needed in 
  225. V86 mode; others only need to be modified as part of a mode switch to 
  226. protected mode.
  227.          
  228. In addition, a number of instructions cause a general protection exception if 
  229. the I/O privilege level (IOPL) is not 3 when executing in V86 mode.  These 
  230. instructions must be made available, either by setting IOPL to 3, or by 
  231. emulating the instructions.
  232.          
  233. 3.0  Interface Summary
  234.          
  235. Many of the problems listed above occur only when one control program uses V86 
  236. mode.  EMS emulators run in V86 mode and are widely used on 386 PCs, and an 
  237. EMS interface is typically used or provided by multitaskers. In addition, one 
  238. of the primary functions performed by EMS emulators is memory allocation.
  239.  
  240. ______________________________________________________________________________
  241.      VCPI Version 1.0           June 12, 1989                      Page 3
  242.  
  243. For these reasons, the VCPI interface is defined as a superset of the EMS 
  244. version 4.0 interface (an EMS 4.0 driver must be provided underneath the VCPI 
  245. interface; a copy of the EMS 4.0 interface specification may be obtained by 
  246. calling Intel literature sales at 1-800-548-4725 and requesting part #300275).  
  247. If an EMS emulator with the VCPI interface is installed, a multitasker and/or 
  248. an arbitrary number of DOS-Extender programs which use the VCPI interface can 
  249. be run.  Control programs which utilize the VCPI interface provided by the EMS 
  250. emulator will be referred to as "clients" for the remainder of this document.  
  251. The control program providing the VCPI interface (and the EMS 4.0 interface) 
  252. will be referred to as the "server" for the remainder of this document.
  253.          
  254. A server is installed at boot time, and takes over a block of extended memory 
  255. which becomes the expanded memory pool from which it allocates EMS pages.  
  256. When the server is installed, it can be given all the extended memory on the 
  257. computer, or extended memory can be "partitioned" into expanded memory and 
  258. extended memory (i.e., some extended memory is taken by the server for the 
  259. expanded memory pool, and the rest is left free, available for use by other 
  260. programs).
  261.          
  262. Clients can obtain memory by making requests of the server.  Memory allocated 
  263. though the VCPI interface comes out of the memory pool owned by the server 
  264. (i.e., expanded memory), and must be in the physical address space of the 
  265. computer (e.g., it must not be memory on a separate expanded memory board).  
  266. If any extended memory is left free by the server, clients can allocate that 
  267. extended memory in the usual way.
  268.          
  269. The VCPI interface is implemented with calls to functions provided by the 
  270. server.  Calls need to be made both in V86 mode and in protected mode.  The 
  271. V86 mode calls are implemented through the standard INT 67h EMS interface.  
  272. The protected mode calls are made with FAR procedure calls to an entry point 
  273. in the server.  The protected mode entry point is obtained via an 
  274. initialization on call to the server.
  275.          
  276. Both the server and each client program maintain their own set of system 
  277. tables (GDT, LDT, IDT, page tables, etc.)  Each client program must initialize 
  278. a memory space in its page tables which is identical to a portion of the 
  279. memory space used by the server, in order to provide a common ground for 
  280. communication with the server.  When the client calls the server to switch to 
  281. protected mode, the client's system tables are set up as part of the mode 
  282. switch.  Likewise, when the client calls the server to switch back to V86 
  283. mode, the server's system tables are set up.
  284.          
  285. The server must leave A20 (address line 20 on a PC) enabled at all times, in 
  286. both V86 mode and in protected mode.
  287.  
  288. The client must always use the services of the server to switch modes. It 
  289. should never, for example, implement its own switch back to V86 mode, because 
  290. the server's system tables must be set up when executing in V86 mode.
  291.          
  292. 4.0  V86 Mode Program Interface
  293.          
  294. The V86 mode interface is provided through the EMS interrupt (INT 67h), with 
  295. an EMS function code in AH of DEh, and a VCPI function code in AL. (Note that 
  296. any EMS driver which does not provide VCPI should return either code 84h (bad 
  297. function code) for this EMS call, since it is not a defined function number 
  298. for the LIM 4.0 EMS specification.)  If the function succeeds, AH is returned 
  299. as zero; otherwise, there is an error code in AH. Except as noted for each 
  300. call, all other registers are unchanged on output. 
  301.  
  302. _______________________________________________________________________________
  303.      VCPI Version 1.0           June 12, 1989                      Page 4
  304.  
  305. If an undefined VCPI subfunction code is passed in AL, the server returns an 
  306. either code in AH; the recommended value is 8Fh (bad subfunction code).
  307.          
  308. The IOPL-sensitive privileged instructions must be available in V86 mode.  
  309. This means the server must either set the IOPL to 3, or emulate these 
  310. instructions.  Other privileged instructions need not be emulated as part of 
  311. the VCPI interface.  Instead, access to certain system registers is provided 
  312. via system calls (see Section 4.4).
  313.          
  314. 4.1  Presence Detection
  315.          
  316. The presence of a server which provides the VCPI interface is detected by 
  317. first using one of the standard detection checks to see if an EMS driver is 
  318. installed, and then making the EMS call below to check for the presence of 
  319. VCPI.
  320.  
  321. ==============================================================================         
  322. INT 67h
  323. AX = DE00h     VCPI Presence Detection
  324. ==============================================================================         
  325. INPUTS:        None
  326. -------------------------------------------------------------------------------         
  327. OUTPUTS:       If VCPI is present:
  328.                     AH = 0
  329.                     BL = 0 (VCPI minor version number, in binary)
  330.                     BH = 1 (VCPI major version number, in binary)
  331.                If not present:
  332.                     AH = nonzero (recommended value:  84h)
  333. -------------------------------------------------------------------------------         
  334.          
  335. If the server is installed but no EMS memory has been allocated, the server 
  336. may be executing in real mode rather than V86 mode.  The detection call should 
  337. return success in real mode as well as V86 mode (so that it is possible to 
  338. detect a VCPI server that is currently turned off, and also for backward 
  339. compatibility with clients that make this call in real mode); however, for the 
  340. rest of the VCPI interface to be enabled, the processor must be executing in 
  341. V86 mode.  Therefore, the following VCPI detection sequence is recommended:
  342.          
  343.      1.  Check to see if the processor is an 80386 or 80486.
  344.      2.  Check to see if an EMS driver is installed.
  345.      3.  Allocate one EMS page.  This will turn on the EMS driver if it is 
  346.          off, switching the processor to V86 mode.
  347.      4.  Make the above VCPI detection call.
  348.          
  349. The EMS page allocated in step 3 must not be deallocated again until the 
  350. client is done using the VCPI interface; otherwise, the server could turn off 
  351. again, setting the processor back to real mode and disabling the VCPI 
  352. interface.
  353.          
  354. Appendix A.3 contains a code sequence demonstrating VCPI detection.
  355.          
  356. 4.2  Interface Initialization
  357.          
  358. The interface initialization process involves creating a common ground between 
  359. the server and the client that allows them to communicate in protected mode, 
  360. and providing any other information that the client may need to complete its
  361.          
  362. ______________________________________________________________________________
  363.      VCPI Version 1.0           June 12, 1989                      Page 5
  364.  
  365. own initialization.  Since the server and the client each have separate page 
  366. tables, GDT, LDT, and IDT, in order to communicate in protected mode the 
  367. client must set up a region in its page tables that maps memory used by the 
  368. server, and must initialize segment descriptors in its GDT to point to code 
  369. and data regions in the server.
  370.          
  371. The calls below are used to initialize the interface between the server and 
  372. the client.
  373.          
  374. ==============================================================================
  375. INT 67h
  376. AX = DE01h     Get Protected Mode Interface
  377. ==============================================================================        
  378. INPUTS:        ES:DI = pointer to 4K page table buffer
  379.                DS:SI = pointer to three descriptor table entries in the 
  380.                        client's GDT, the first to be set up as the 
  381.                        protected mode code segment in the server, and the 
  382.                        additional two entries to be used as desired by 
  383.                        the server when it is called in protected mode
  384. -------------------------------------------------------------------------------         
  385. OUTPUTS:       AH = 0
  386.                DI = advanced to point to the first unused page table 
  387.                     entry in the buffer (could be advanced by 4K, if 
  388.                     server initializes entire page table)
  389.                EBX = offset in code segment of protected mode entry point
  390. -------------------------------------------------------------------------------         
  391.  
  392. The Get Protected Mode Interface call is used to set up a common frame of 
  393. reference which allows the client to make calls to the server in protected 
  394. mode.  The call initializes a page table which the client must set up as its 
  395. 0th page table.  This page table must map at least one megabyte of memory 
  396. starting at linear address zero:  the real mode address space provided in V86 
  397. mode.  In addition, the server can map any additional memory above one 
  398. megabyte (up to a total of four megabytes, since there is just one page table) 
  399. which it requires to provide the protected mode interface.  While the mappings 
  400. for the first megabyte must be identical for both the client and the server 
  401. (so the client will be able to set up segments to access its V86 memory from 
  402. protected mode), memory above one megabyte can be mapped as desired by the 
  403. server (e.g., if the server's code and data is mapped at a high address in its 
  404. own page tables, it would simply map the same code and data just above one 
  405. megabyte in the client's 0th page table).
  406.          
  407. For backward compatibility, both the server and the client must clear the 
  408. software-defined bits (bits 9 - 11) in the page table entries it copies into 
  409. the client's page table; all other bits should be preserved the client must 
  410. not copy its 0th page table to a different physical page after this call is 
  411. made.  This is so the server can always access the client's 0th page table.  
  412. The client must never modify any bits other than the software-defined bits (9-
  413. 11) in the page table entries which are initialized by this call.
  414.          
  415. In addition to initializing the 0th page table, this call also fills in a GDT 
  416. entry in the client's GDT.  This segment is used by the client when calling 
  417. the server in protected mode.  The segment must be set up as a code segment, 
  418. and must reside in the linear address space set up in the 0th page table by 
  419. this call.  The entry point of the interface routine (its offset within the 
  420. code segment) is returned in EBX.  Two additional entries in the client's GDT, 
  421. immediately following the GDT entry for the code segment, are available to the 
  422. server for its own use.  Typically at least one of these GDT segments is used 
  423. by the server as a data segment.
  424.  
  425. ______________________________________________________________________________
  426.      VCPI Version 1.0           June 12, 1989                      Page 6
  427.  
  428. When the client calls the server in protected mode, it makes a FAR call to a 
  429. USE32 segment, using the entry point provided by this call.  Since the server 
  430. has initialized the code segment descriptor, it can, of course, set it up any 
  431. way it desires, but it is responsible for executing a USE32 FAR return when it 
  432. terminates, regardless of the actual use type of the code segment.  Thus, when 
  433. the server is called in protected mode, it will have CS pointing to the code 
  434. segment which is set up by this call.  It can obtain selectors for the two 
  435. additional GDT entries which it set up by adding 0008h and 0010h, 
  436. respectively, to the segment selector value in CS.  The server must preserve 
  437. all segment registers across a protected mode VCPI call.
  438.  
  439. ==============================================================================
  440. INT 67h
  441. AX = DE02h     Get Maximum Physical Memory Address
  442. ==============================================================================
  443. INPUTS:        None
  444. ------------------------------------------------------------------------------
  445. OUTPUTS:       AH = 0
  446.                EDX = PHYSICAL address of the highest 4K memory page that 
  447.                      could ever be allocated.
  448. ------------------------------------------------------------------------------
  449.  
  450. The Get Maximum Physical Memory Address call is used by the client to 
  451. initialize its memory management data structures.  To do this, it may need to 
  452. know the physical address of the highest 4K memory page that could ever be 
  453. allocated by the Allocate 4K Page call specified below.  For backward 
  454. compatibility, both the server and the client must mask the 12 LSBs of the 
  455. physical page address (returned in EDX) to zero.
  456.          
  457. 4.3  Memory Allocation Calls
  458.          
  459. The memory allocation calls are used to allocate and free 4K pages of memory. 
  460. The server allocates these pages out of its EMS memory pool.  The client can 
  461. also do its own allocation of extended memory or XMS memory, if any is 
  462. available.
  463.  
  464. ==============================================================================
  465. INT 67h
  466. AX = DE03h     Get Number of Free 4K Pages
  467. ===============================================================================
  468. INPUTS:        None
  469. -------------------------------------------------------------------------------         
  470. OUTPUTS:       AH = 0
  471.                EDX = number of free 4K pages
  472. -------------------------------------------------------------------------------
  473.  
  474. This call returns the total number of 4K pages available to be allocated out 
  475. of the server's expanded memory pool.
  476.          
  477. Note that this is the total amount of free memory available to all tasks on 
  478. the system.  The client should allocate this memory only on an as needed 
  479. basis. In addition, in a multitasking environment, this number does not 
  480. reflect any memory restrictions placed on the client task by the multitasker.  
  481. The client should, during initialization, use the EMS call Get Number of Pages 
  482. (INT 67h function 3 (AH=42h)) to obtain the number of unallocated EMS pages 
  483. available, and then limit its usage of memory allocated through the server to 
  484. that amount.  (Note that the size of an EMS page is 16K, and the size of a 
  485. page allocated through the VCPI interface is 4K.)
  486.  
  487. ______________________________________________________________________________
  488.      VCPI Version 1.0           June 12, 1989                      Page 7
  489.  
  490. ==============================================================================
  491. INT 67h
  492. AX = DE04h     Allocate a 4K Page
  493. ===============================================================================         
  494. INPUTS:        None
  495. -------------------------------------------------------------------------------         
  496. OUTPUTS:       If success:
  497.                     AH = 0
  498.                     EDX = PHYSICAL address of allocated 4K page
  499.                If failure:
  500.                     AH = nonzero (recommended value:  88h)
  501.                     EDX = contents modified
  502. -------------------------------------------------------------------------------         
  503.  
  504. This call allocates a 4K page of memory.  For backward compatibility, both the 
  505. server and client must make the 12 LSBs of the physical page address (returned 
  506. in EDX) to zero.  The client is responsible for freeing all memory allocated 
  507. with this call before terminating execution.
  508.          
  509. ==============================================================================
  510. INT 67h
  511. AX = DE05h     Free a 4K Page
  512. ===============================================================================         
  513. INPUTS:        EDX = PHYSICAL address of 4K page to free
  514. -------------------------------------------------------------------------------
  515. OUTPUTS:       If success:
  516.                     AH = 0
  517.                If failure:
  518.                     AH = nonzero (recommended value:  8Ah)
  519. -------------------------------------------------------------------------------        
  520.  
  521. This call frees a page of memory previously allocated with subfunction 04h. 
  522. For backward compatibility, both the server and the client must mask the 12 
  523. LSBs of the physical page address (passed in EDX) to zero.
  524.  
  525. ______________________________________________________________________________
  526.      VCPI Version 1.0           June 12, 1989                      Page 8
  527.  
  528. ==============================================================================
  529. INT 67h
  530. AX = DE06h     Get Physical Address of 4K Page in First Megabyte
  531. ===============================================================================         
  532. INPUTS:        CX = page number (linear address of page SHR 12)
  533. -------------------------------------------------------------------------------
  534. OUTPUTS:       If success:
  535.                     AH = 0
  536.                     EDX = PHYSICAL address of 4K page
  537.                If invalid page number:
  538.                     AH = nonzero (recommended value:  8Bh)
  539. -------------------------------------------------------------------------------         
  540.  
  541. This call returns the physical address of a 4K page in the first megabyte of 
  542. the V86 mode linear address space.  For backward compatibility, both the 
  543. server and the client must mask the 12 LSBs of the physical page address 
  544. (returned in EDX) to zero.
  545.          
  546. This call is useful for obtaining the address of memory which is allocated and 
  547. mapped into the first megabyte with the standard EMS calls.  While this 
  548. information can also be extracted from the page table obtained with the Get 
  549. Protected Mode Interface system call, that page table is a "snapshot" of the 
  550. server's page tables at the time the system call was made, and would not have 
  551. the correct addresses for any EMS memory mapped in after the Get Protected 
  552. Mode Interface call was made.
  553.  
  554. 4.4  System Register Access Calls
  555.          
  556. When executing in V86 mode, any attempt to load or store system registers 
  557. causes a general protection exception.  The system calls below provide access 
  558. to certain system registers in V86 mode.
  559.  
  560. ===============================================================================
  561. INT 67h
  562. AX = DE07h     Read CR0
  563. ===============================================================================
  564. INPUTS:        None
  565. -------------------------------------------------------------------------------         
  566. OUTPUTS:       AH = 0
  567.                EBX = CR0 value
  568. -------------------------------------------------------------------------------         
  569.          
  570. This call returns the current value of the CR0 register.
  571.  
  572. ______________________________________________________________________________
  573.      VCPI Version 1.0           June 12, 1989                      Page 9
  574.  
  575. ===============================================================================
  576. INT 67h
  577. AX = DE08h     Read Debug Registers
  578. ===============================================================================
  579. INPUTS:        ES:DI = pointer to array of 8 DWORDS, DR0 first in 
  580.                        array, DR4 and DR5 not used
  581. -------------------------------------------------------------------------------
  582. OUTPUTS:       AH = 0
  583. -------------------------------------------------------------------------------
  584.  
  585. This call stores the values of the debug registers into an array in memory. 
  586.  
  587.  
  588. ===============================================================================
  589. INT 67h
  590. AX = DE09h     Load Debug Registers
  591. ===============================================================================
  592. INPUTS:        ES:DI = pointer to array of 8 DWORDS, DR0 first in array, 
  593.                        DR4 and DR5 not used
  594. -------------------------------------------------------------------------------
  595. OUTPUTS:       AH = 0
  596. -------------------------------------------------------------------------------
  597.          
  598. This function loads the debug registers with the values in the array.
  599.          
  600. 4.5  8259A Interrupt Vector Mapping Calls
  601.          
  602. The default PC interrupt vector assignments for hardware interrupts are 
  603. vectors 08h - 0Fh for interrupts IRQ0 - IRQ7, and vectors 70h - 77h for 
  604. interrupts IRQ8 - IRQ15.  The 80386 processor uses interrupt vectors 08h - 0Fh 
  605. for processor exceptions, which are important to 386-specific software.  
  606. Therefore, some clients find it desirable to reprogram the 8259A interrupt 
  607. controller to map the hardware interrupt vectors elsewhere in the interrupt 
  608. space.  The server, as the first control program in place, is the repository 
  609. of information on what the current vector mappings are.  Client programs 
  610. should query the server during initialization to determine the current 
  611. mappings. If they have been changed from the PC default mappings, the client 
  612. is obligated not to change them again.  If they are still set to the PC 
  613. defaults, the client can reprogram the interrupt controller and then inform 
  614. the server what the new mappings are.
  615.  
  616. ______________________________________________________________________________
  617.      VCPI Version 1.0           June 12, 1989                      Page 10
  618.  
  619. ===============================================================================
  620. INT 67h
  621. AX = DE0Ah     Get 8259A Interrupt Vector Mappings
  622. ===============================================================================
  623. INPUTS:        None
  624. -------------------------------------------------------------------------------
  625. OUTPUTS:       AH = 0
  626.                BX = 1st vector mapping for master 8259A (IRQ0-IRQ7)
  627.                CX = 1st vector mapping for slave 8259A (IRQ8-IRQ15)
  628. -------------------------------------------------------------------------------
  629.          
  630. This function returns the interrupt vectors generated by the 8259A interrupt 
  631. controller chips when a hardware interrupt occurs.  If there is no slave 8259A 
  632. to generate IRQ8-IRQ15 (because the software is running on a 386 accelerator 
  633. card plugged into a PC or a PC/XT), then the value returned in CX is 
  634. unspecified.
  635.          
  636. Note that, for programs who wish to take over hardware interrupts in V86 mode, 
  637. other considerations may apply when executing in a multitasking environment.
  638.  
  639. ===============================================================================
  640. INT 67h
  641. AX = DE0Bh     Set 8259A Interrupt Vector Mappings
  642. ===============================================================================
  643.          
  644. INPUTS:        BX = vector mapping for master 8259A (IRQ0-IRQ7)
  645.                CX = vector mapping for slave 8259A (IRQ8-IRQ15)
  646.                Interrupts disabled
  647. -------------------------------------------------------------------------------         
  648. OUTPUTS:       AH = 0
  649. -------------------------------------------------------------------------------
  650.          
  651. This call is used by the client to inform the server if it remaps the 8259A 
  652. interrupt controllers.  The client must leave interrupts disabled from the 
  653. time it begins to reprogram the interrupt controllers until after it makes 
  654. this function call to inform the server of the remapping.
  655.          
  656. Note that the server must leave interrupts disabled until after it has logged 
  657. the vector mappings provided by the call.  In particular, it must not 
  658. "reflect" the interrupt back to V86 mode before recording the information, in 
  659. case there is another program in the INT 67h chain which enables interrupts.
  660.          
  661. If the client remaps the 8259A interrupt controller, it is responsible for 
  662. restoring the original interrupt controller mappings when it terminates.
  663.          
  664. ______________________________________________________________________________
  665.      VCPI Version 1.0           June 12, 1989                      Page 11
  666.  
  667. 4.6  Switch to Protected Mode
  668.          
  669. ===============================================================================
  670. INT 67h
  671. AX = DE0Ch     Switch From V86 Mode to Protected Mode
  672. ===============================================================================
  673. INPUTS:        ESI = linear address of data structure in first megabyte, 
  674.                      containing values to load into system registers
  675.                Interrupts disabled
  676. -------------------------------------------------------------------------------         
  677. OUTPUTS:       GDTR, IDTR, LDTR, TR loaded
  678.                Interrupts disabled
  679.                Control transferred to specified FAR entry point
  680.                SS:ESP must have at least 16 BYTEs of space on it, and the 
  681.                       protected mode entry point is required to set up its 
  682.                       own stack before re-enabling interrupts
  683.                EAX = contents modified
  684.                ESI = contents modified
  685.                DS, ES, FS, GS = contents modified
  686.                All other registers unmodified
  687. -------------------------------------------------------------------------------
  688.          
  689. This call switches to protected mode, sets up all the system tables for the 
  690. client, and transfers control to the specified entry point in the client.  
  691. Interrupts must remain disabled for the entire duration of the switch.  The 
  692. ESI register contains a linear address of a data structure in the first 
  693. megabyte; because the page table mappings for the first megabyte are identical 
  694. in both the server's and the client's page tables, this address can be used by 
  695. the server both before and after reloading the CR3 register.
  696.          
  697. The data structure pointed to by ESI looks like:
  698.          
  699.      10 (DWORD) CS:EIP too transfer control to
  700.      0E (WORD)  selector value to load into TR
  701.      0C (WORD)  selector value to load into LDTR
  702.      08 (DWORD) linear address in first megabyte of 6-byte value to
  703.                 load into IDTR
  704.      04 (DWORD) linear address in first megabyte of 6-byte value to
  705.                 load into GDTR
  706. ESI->00 (DWORD) new value to load into CR3
  707.  
  708. Note that the server must load GDTR before loading the LDTR and TR (IDTR can 
  709. be loaded at any time, since interrupts are disabled).  The GDTR and IDTR must 
  710. be loaded with the 32-bit forms of the LGDT and LIDT instructions, not the 24-
  711. bit forms provided for backward compatibility with the 80286 processor.  The 
  712. server must clear the task busy bit in the TSS descriptor table entry in the 
  713. client's GDT before loading TR (which must be loaded with an LTR instruction, 
  714. not a task switch).  Note that, since the client's GDT could reside anywhere 
  715. in the 4 GB linear address space, the TSS descriptor table entry cannot be 
  716. modified (and the LDTR and TR registers cannot be loaded) until after CR3 is 
  717. loaded with the client's value, and the data segment used to modify the TSS 
  718. descriptor must have a base address of zero and a limit of 4 GB.  The server 
  719. must not reload any segment registers after it loads the GDTR with the 
  720. client's GDT address; note that the ability to modify GDTR and LDTR without 
  721. reloading segment registers relies on the segment descriptor caching performed 
  722. by the processor.  
  723.  
  724. ______________________________________________________________________________
  725.      VCPI Version 1.0           June 12, 1989                      Page 12
  726.  
  727. The server's code that implements the switch must reside in the linear region 
  728. that was initialized with the Get Protected Mode Interface call (function 
  729. DE01h), since that is the only linear region that is mapped identically in 
  730. both the server's and the client's page tables.
  731.          
  732. When the client gets control, the stack is still set to whatever stack the 
  733. server was using (because SS has not been reloaded, the descriptor cache 
  734. register for SS still points to the server's stack segment).  The client must 
  735. reload all segment registers and set up its own stack before enabling 
  736. interrupts.  This is a requirement since an interrupt handler will attempt to 
  737. save and restore segment registers, and the values left in the segment 
  738. registers after the switch are not necessarily valid segments for the client.
  739.          
  740. 5.0  Protected Mode Interface
  741.          
  742. The protected mode interface is a FAR entry point in the server, which is 
  743. obtained during initialization with the Get Protected Mode Interface system 
  744. call (INT 67h function DE01h).  The client makes a FAR call to a USE32 segment 
  745. when it calls the server entry point, and the server must execute a USE32 FAR 
  746. return when it terminates.
  747.          
  748. An EMS function code of DEh is passed in AH, and a VCPI function code is 
  749. passed in AL.  If the function succeeds, AH is returned as zero; otherwise, 
  750. there is an error code in AH.  Except as noted for each call, all other 
  751. registers are unchanged on output.
  752.          
  753. If an undefined VCPI subfunction code is passed in AL, the server returns an 
  754. error code in AH; the recommended value is 8Fh (bad subfunction code).
  755.          
  756. 5.1  Memory Allocation Calls
  757.          
  758. The memory allocation calls are used to allocate and free 4K pages of memory 
  759. the server allocates these pages out of its expanded memory pool.  The client 
  760. can also do its own allocation of extended memory or XMS memory, if any is 
  761. available.
  762.  
  763. ===============================================================================
  764. INT 67h         
  765. AX = DE03h     Get Number of Free 4K Pages
  766. ===============================================================================
  767. INPUTS:        None
  768. -------------------------------------------------------------------------------
  769. OUTPUTS:       AH = 0
  770.                EDX = number of free 4K pages
  771. -------------------------------------------------------------------------------
  772.          
  773. This call returns the total number of 4K pages available to be allocated out 
  774. of the server's expanded memory pool.
  775.          
  776. Note that this is the total amount of free memory available to all tasks on 
  777. the system.  The client should allocate this memory only on an as needed 
  778. basis.  In addition, in a multitasking environment, this number does not 
  779. reflect any memory restrictions placed on the client task by the multitasker.  
  780. The client should, during initialization, use the EMS call Get Number of Pages 
  781. (INT 67h function 3 (AH = 42h)) to obtain the number of unallocated EMS pages 
  782. available, and then limit its usage of memory allocated through the server to 
  783. that amount.  (Note that the size of an EMS page is 16K, and the size of a 
  784. page allocated through the VCPI interface is 4K.)
  785.           
  786. ______________________________________________________________________________
  787.      VCPI Version 1.0           June 12, 1989                      Page 13
  788.  
  789. ===============================================================================
  790. INT 67h
  791. AX = DE04h     Allocate a 4K page         
  792. ===============================================================================
  793. INPUTS:        None
  794. -------------------------------------------------------------------------------
  795. OUTPUTS:       If success:
  796.                     AH = 0
  797.                     EDX = PHYSICAL address of allocated 4K page
  798.                If failure:
  799.                     AH = nonzero (recommended value:  88h)
  800.                     EDX = contents modified
  801. -------------------------------------------------------------------------------
  802.          
  803. This call allocates a 4K page of memory.  For backward compatibility, both the 
  804. server and client must mask the 12 LSBs of the physical page address (returned 
  805. in EDX) to zero.  The client is responsible for freeing all memory allocated 
  806. with this call before terminating execution.
  807.  
  808.  
  809. ===============================================================================
  810. INT 67h         
  811. AX = DE05h     Free a 4K Page
  812. ===============================================================================
  813. INPUTS:        EDX = PHYSICAL address of allocated 4K page
  814. -------------------------------------------------------------------------------
  815. OUTPUTS:       If success:
  816.                     AH = 0
  817.                If failure:
  818.                     AH = nonzero (recommended value:  8Ah)
  819. -------------------------------------------------------------------------------
  820.  
  821. This call frees a page of memory previously allocated with subfunction 04h. 
  822. For backward compatibility, both the server and the client must mask the 12 
  823. LSBs of the physical page address (passed in EDX) to zero.
  824.          
  825. ______________________________________________________________________________
  826.      VCPI Version 1.0           June 12, 1989                      Page 14
  827.  
  828. 5.2  Switch to V86 Mode
  829.          
  830. ===============================================================================
  831. INT 67h
  832. AX = DE0Ch     Switch From Protected Mode to V86 Mode
  833. ===============================================================================
  834. INPUTS:        Top of stack looks as described below
  835.                Interrupts disabled
  836.                SS:ESP must be in the first megabyte of linear memory
  837.                DS = segment selector that maps the entire linear address space 
  838.                     that was obtained with subfunction 01h, Get Protected Mode 
  839.                     Interface (i.e., its base address is 0, and its limit is 
  840.                     the size of the address space obtained with the Get 
  841.                     Protected Mode Interface call)
  842. -------------------------------------------------------------------------------         
  843. OUTPUTS:       GDTR, IDTR, LDTR, TR loaded with server's values
  844.                Interrupts disabled
  845.                Control transferred to specified FAR entry point
  846.                SS:ESP and all segment registers loaded with values on stack
  847.                EAX = destroyed
  848.                All other registers unmodified
  849. -------------------------------------------------------------------------------
  850.          
  851. This call switches from protected mode back to V86 mode, after setting up all 
  852. of the server's system tables.  The top of stack looks as follows on input to 
  853. this function:
  854.          
  855.          28 (DWORD) GS value
  856.          24 (DWORD) FS value
  857.          20 (DWORD) DS value
  858.          1C (DWORD) ES value
  859.          18 (DWORD) SS value
  860.          14 (DWORD) ESP value
  861.          10 (DWORD) reserved for EFLAGS value
  862.          0C (DWORD) CS value
  863.          08 (DWORD) EIP value
  864. SS:ESP-> 00 (DWORD) return address from FAR call to USE32 segment
  865.          
  866. The first 8 bytes at SS:ESP are the return address pushed by the FAR CAlL 
  867. instruction; since this call never returns, the return address is irrelevant 
  868. and should be discarded.  It is the responsibility of the server to fill in an 
  869. appropriate EFLAGS value (e.g., VM bit set, IOPL = 3, IF bit cleared) before 
  870. executing the IRETD to return to V86 mode.  Interrupts must remain disabled 
  871. for the entire duration of the switch, and the interrupt enable bit must be 
  872. off in the EFLAGS value which is stored on the stack before executing the 
  873. IRETD which switches back to V86 mode.  The server's code that implements the 
  874. switch must reside in the linear region that was initialized with the Get 
  875. Protected Mode Interface call (function DE01h), since that is the only linear 
  876. region that is mapped identically in both the server's and the client's page 
  877. tables.
  878.          
  879. If the client does any task switching, it should clear the TS bit in CR0 
  880. before making this call.  Otherwise, the TS bit will still be set after the 
  881. switch to V86 mode, and a floating point coprocessor instruction in V86 mode 
  882. will cause an exception 7 trap to the server.
  883.          
  884. ______________________________________________________________________________
  885.      VCPI Version 1.0           June 12, 1989                      Page 15
  886.  
  887.                                  Appendix A
  888.          
  889. Implementation Notes
  890.          
  891. A.1  Top-Down Extended Memory Allocation
  892.          
  893. The BIOS extended memory size system call is used to determine the upper limit 
  894. of extended memory which is not in use by other programs.  The following code 
  895. fragment gets the physical address of one byte past the end of available 
  896. extended memory in the EAX register:
  897.          
  898.      xor  eax,eax             ; clear MSBs in EAX
  899.      mov  ah, 88h             ; get size of extended memory in KB
  900.      int  15h
  901.      shl  eax, 10             ; convert it address of top of memory
  902.      add  eax, 100000h         
  903.  
  904. To allocate extended memory top down, simply install an INT 15h handler which 
  905. passes all functions except 88h through to the previous INT 15h handler.  If 
  906. an INT 15h function 88h call is made, return a value which reduces the size of 
  907. extended memory by the amount of memory you wish to allocate.
  908.          
  909. A.2  Bottom-Up Extended Memory Allocation
  910.          
  911. Bottom-up extended memory allocation is not recommended, as it is more 
  912. complicated and less versatile than top-down allocation.  However, programs 
  913. that wish to allocate extended memory must first check to see if any other 
  914. programs have allocated extended memory using the bottom-up technique.  Bottom-
  915. up extended memory allocation is done by marking the amount of memory 
  916. allocated in two locations.  If there is any extended memory on the system (if 
  917. the BIOS call documented in Appendix A.1 does not return zero), it is 
  918. necessary to check BOTH of these locations to see if any bottom-up extended 
  919. memory has been allocated.  If the two locations show different amounts of 
  920. allocated memory, the safest thing to do is terminate with an error message.  
  921. Failing that, the larger of the two values found should be used.  The values 
  922. may differ in the two locations because there are several programs available 
  923. which use bottom-up allocation but which do not correctly update both 
  924. locations, and also because the DOS PRINT command in DOS 3.3 or later wipes 
  925. out the allocation information in one of the two locations.
  926.          
  927. The first location is the segment pointed at by the INT 19h vector (the reboot 
  928. interrupt).  If an appropriate signature is present at a specific offset in 
  929. this segment, then there is a 24-bit address of the first free byte of 
  930. extended memory at another specific offset in the segment.  The following code 
  931. fragment obtains the physical address of the first free byte of extended 
  932. memory and loads it into EAX:
  933.          
  934.      data segment
  935.           vdisk_sig db 'VDISK V'       ; signature string
  936.           SIG _ LEN equ $ - vdisk_sig  ; signature string length
  937.           SIG_VEC equ 19h              ; interrupt vector for signature
  938.           SIG_OFFS equ 12h             ; offset of signature string in segment
  939.           LO_OFFS equ 2Ch              ; offset of low word of 24-bit value
  940.           HI_OFFS equ 2Eh              ; offset of high byte of 24-bit value
  941.           data ends
  942.                                                  
  943. ______________________________________________________________________________
  944.      VCPI Version 1.0           June 12, 1989                      Page 16
  945.  
  946.      assume    cs:code,ds:data
  947.      code      segment use16
  948.          
  949.           xor ax,ax                 ; get segment addr in ES
  950.           mov es,ax
  951.           mov ax,es:(SIG_VEC * 4) + 2 
  952.           mov es,ax
  953.          
  954.           mov di,SIG_OFFS           ; branch of signature not present
  955.           lea si,vdisk_sig
  956.           mov ex,SIG_LEN
  957.           cld
  958.           repe cmpsb
  959.           jne short no_alloc
  960.          
  961.           xor eax,eax               ; get addr of bottom of extended memory
  962.           mov al,es:HI_OFFS         ; into EAX
  963.           shl eax,16
  964.           mov ax,es:LO_OFFS
  965.           jmp short done            ; all done
  966.          
  967.      no_alloc:
  968.                mov eax,100000h      ; no bottom-up memory allocated
  969.          
  970.      done:                          ; bottom of extended memory is now in EAX
  971.      code ends
  972.          
  973. The second location to check is a boot block located at one megabyte.  The 
  974. following C code fragment retrieves the allocation value from the boot block 
  975. and saves it in the variable "bot_ext" (note that this code should NOT be 
  976. executed if there is no extended memory on the system, since it attempts to 
  977. read memory at one megabyte):
  978.          
  979.      long bot_ext;        /* addr of 1st free byte of extended memory */
  980.      char buf [0x20];     /* buffers boot block */
  981.      #define SIGOFF 0x03  /* offset of signature in boot block */
  982.      #define SIZEOFF 0x1E /* offset of size word in boot block */
  983.          
  984.      /*
  985.      * Read boot block at one megabyte by calling an assembly language 
  986.      * routine (not shown) which either uses the BIOS block move call to 
  987.      * read from extended memory, or does it in some other way.
  988.      */
  989.          
  990.      read_ext(0x100000, buf, sizeof(buf));
  991.          
  992.      /*
  993.      * Now check for the correct signature in the boot block, and if 
  994.      * present, extract the bottom of available extended memory.
  995.      */
  996.          
  997.      if (memcmp(&buf[SIGOFF], "VDISK", 5) != 0)
  998.           bot_ext = 0x100000;
  999.      else
  1000.      {
  1001.           bot_ext = 01;
  1002.           memcpy(&bot_ext, &buf[SIZEOFF], 2]; /* get KB addr */
  1003.           bot_ext = bot_ext << 10;            /* convert to byte addr */
  1004.          
  1005. ______________________________________________________________________________
  1006.      VCPI Version 1.0           June 12, 1989                      Page 17
  1007.  
  1008. A.3  Sample VCPI Detection Code
  1009.          
  1010. The following code sequence should be used to detect the presence of the VCPI 
  1011. interface:
  1012.          
  1013.      data segment
  1014.      emm_name db 'EMMXXXX0',0      ; device name for EMM
  1015.      data ends
  1016.          
  1017.           assume      cs:code,ds:data
  1018.      code segment use16
  1019.      ;
  1020.      ; First check to make sure we are on an 80386 or 80486
  1021.      ;
  1022.           pushf               ; save flags
  1023.           xor ax,ax           ; try to put a zero word into flags and then
  1024.           push ax             ; get result back into AX
  1025.           popf
  1026.           pushf           
  1027.           pop ax
  1028.           and ax,0F000h       ; if high 4 bits of flags are all 1's, it's an
  1029.           cmp ax,0F000h       ; 8086/8088/80186/80188
  1030.           jne short not_386
  1031.           mov ax,0F000h       ; Now try to set the high 4 bits of the flags 
  1032.           push ax             ; and then get the result back in AX
  1033.           popf
  1034.           pushf
  1035.           pop ax
  1036.           and ax,0F000h        ; if none of the high 4 bits are set, it's an
  1037.           jz short not_386     ; 80286 -- otherwise, it's a 386 or 486
  1038.           popf                 ; restore flags
  1039.           jmp short ems_check  ; go to next check
  1040.      not_386:
  1041.           popf                 ; restore flags
  1042.           jmp no_vcpi          ; not a 386 or 486 -- VCPI not present
  1043.  
  1044.      ems_check:
  1045.      ;
  1046.      ; Check for EMS driver present
  1047.      ;
  1048.           lea dx,emm_name      ; open EMM device, read-only
  1049.           mov ax,3D00h
  1050.           int 21h
  1051.           jc short no_vcpi     ; branch if error
  1052.           mov bx,ax            ; get device information
  1053.           mov ax,4400h
  1054.           int 21h
  1055.           jc short no_vcpi     ; branch if error
  1056.           test dx,80h          ; branch if file (not device)
  1057.           jz short no_vcpi
  1058.           mov ax,4407h         ; check output status
  1059.           int 21h
  1060.           push ax              ; save return code from IOCTL call
  1061.           mov ah,3Eh           ; close file
  1062.           int 21h
  1063.           pop ax               ; restore IOCTL return code
  1064.           cmp al,0FFh          ; branch if status not device ready
  1065.           jne short no_vcpi
  1066.          
  1067. ______________________________________________________________________________
  1068.      VCPI Version 1.0           June 12, 1989                      Page 18
  1069.  
  1070.      ; Now allocate an EMS page to make sure the EMS emulator is turned on.
  1071.      ; Note that we must save the handle for this allocated page and free it
  1072.      ; again eventually, although this is not shown in the code fragment.
  1073.      ;
  1074.          mov bx,1           ; allocate 1 EMS page
  1075.          mov ah,43h
  1076.          int 67h
  1077.          cmp ah,0          ; branch if error
  1078.          jne short no_vcpi
  1079.      ; save handle returned in DX to be freed later
  1080.          
  1081.      ; Now make VCPI detection call
  1082.      ;
  1083.          mov ax,0DE00h        ; is VCPI there?
  1084.          int 67h
  1085.          cmp ah,0             ; branch if not there
  1086.          jne short no_vcpi
  1087.      ; OK, the VCPI interface is present and the server is turned on.
  1088.      no_vcpi:                 ; VCPI interface not present
  1089.      code ends
  1090.          
  1091. ______________________________________________________________________________
  1092.      VCPI Version 1.0           June 12, 1989                      Page 19
  1093.  
  1094.  
  1095.                                   GLOSSARY
  1096.          
  1097. 4K page                  A four-kilobyte page, the page size allocated by 
  1098.                          calls to the VCPI interface.  A 4K page is always 
  1099.                          aligned on a four-kilobyte physical address boundary.
  1100.          
  1101. A20                      Address line 20.  On AT and MCA architectures, there 
  1102.                          is hardware to truncate physical addresses to 20 bits 
  1103.                          (one megabyte).  This is known as "disabling A20," and 
  1104.                          is for compatibility with 8086 programs which rely on 
  1105.                          address wraparound at one megabyte.  To use extended 
  1106.                          memory, it is necessary to "enable A20."
  1107.          
  1108. bottom-up allocation     Allocation of extended memory starting at one 
  1109.                          megabyte and growing upward.  This allocation method 
  1110.                          is used by older VDISK device drivers.
  1111.  
  1112. client                   A program which uses the VCPI interface 
  1113.  
  1114. expanded memory          Memory allocated by an EMS emulator 
  1115.  
  1116. extended memory          Physical memory above one megabyte.
  1117.          
  1118. EMS page                 A 16-kilobyte page, the page size allocated by calls 
  1119.                          to an EMS driver.  An EMS page is always allocated on 
  1120.                          a four-kilobyte physical address boundary.
  1121.          
  1122. real mode address space  Linear addresses below one megabyte (note that this 
  1123.                          does not necessarily correspond to physical addresses 
  1124.                          below one megabyte)
  1125.  
  1126. server                   A program which provides the VCPI interface
  1127.          
  1128. top-down allocation      Allocation of extended memory starting at the top of 
  1129.                          memory and growing downward.  This is the recommended 
  1130.                          technique for allocating extended memory.
  1131.          
  1132. ______________________________________________________________________________
  1133.      VCPI Version 1.0           June 12, 1989                      Page 20
  1134.